package cn.gwm.flink.streaming.dwm.charge.support;

import cn.gwm.flink.streaming.constant.BaseFields;
import cn.gwm.flink.streaming.constant.VehicleType;
import cn.gwm.flink.streaming.dwm.charge.assist.gps.GpsMatchFactory;
import cn.gwm.flink.streaming.dwm.charge.bean.ChargeArgs;
import cn.gwm.flink.streaming.dwm.charge.bean.ChargeFavourable;
import cn.gwm.flink.streaming.dwm.charge.model.ChargeConstant;
import cn.gwm.flink.streaming.dwm.charge.model.ChargeTypeEnum;
import cn.gwm.flink.streaming.dwm.charge.template.ChargeStateModel;
import cn.gwm.flink.streaming.dwm.charge.util.ModeCodeUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.flink.api.common.state.MapState;

import java.util.Map;

/**
 * @ClassName ChargeStateSupport
 * @Description 充电主题协助类，用以协助完成充电状态各对象生成或处理
 * @Author LiangGuang
 * @Date 2023/05/11 16:13
 */
@Slf4j
public class ChargeStateSupport {


    public static JSONObject createSummar(ChargeConstant constant, JSONObject sourceData,
                                          Long ConnectTime, MapState<String, JSONObject> chargeModelFirstState, Integer complete) throws Exception {
        JSONObject summar = JSONUtil.createObj();
        summar.set(VehicleType.VEHICLE_TYPE, sourceData.getStr(VehicleType.VEHICLE_TYPE));
        summar.set(BaseFields.tid, sourceData.getLong(BaseFields.tid));
        summar.set(BaseFields.vin, sourceData.getStr(BaseFields.vin));
        // 此处 datedt 可以直接使用 dwd传过来的 datedt 而不用自己转换
        summar.set(BaseFields.PARTITION_KEY, DateUtil.format(DateUtil.date(sourceData.getLong(BaseFields.tid)), DatePattern.NORM_DATE_PATTERN));
        summar.set("chrgConnectTid", ConnectTime);
        summar.set("chrgLogicNum", 0);
        summar.set("Tbox_BattSOCLim", sourceData.get(constant.getTboxBattSoc()));
        summar.set("model_code", sourceData.getStr(constant.getModelCode()));
        summar.set("BMS_SWVersion", sourceData.getStr(constant.getBmsSWVersion()));
        summar.set("custom_type", sourceData.getStr(constant.getCustomType()));
        // 补充经纬度
        summar.set(BaseFields.LATITUDE, sourceData.getStr(constant.getLatitude()));
        summar.set(BaseFields.LONGITUDE, sourceData.getStr(constant.getLongitude()));
        summar.set("complete", complete);

        summar.set("discountPower", 0);
        summar.set("expensivePower", 0);
        summar.set("discountTime", 0);
        summar.set("expensiveTime", 0);

        if (sourceData.getInt(constant.getBmsDcchrgConnect()) == 1) {
            // 快充
            summar.set("BMS_DCChrgConnect", 1);
            summar.set("OBC_ConnectSts_EV", 0);
        } else {
            summar.set("BMS_DCChrgConnect", 0);
            summar.set("OBC_ConnectSts_EV", 1);
        }
        // 先赋 其他【未知类型】 ，充电中如果判断出来则会重新赋值
        summar.set("chargeType", ChargeTypeEnum.CHARGE_TYPE_TO_BE_IDENTIFIED.getCode());
        // 充电模式
        if (!BaseFields.defaultVal.equals(sourceData.getStr(constant.getPlugChrgnMode()))) {
            String chargeModel = ChargeFieldSupport.chargeModel(sourceData, constant);
            if (!BaseFields.defaultVal.equals(chargeModel)) {
                summar.set("chargeModel", chargeModel);
                // 首个模式 如果模式达到10分钟则变为ture，再次模式超过10分钟 则 多模式
                summar.set("chargeModelFlag", false);
                chargeModelFirstState.put(chargeModel, sourceData);
            }
        }
        return summar;
    }


    /**
     * 补充 字段 经纬度，及相关 汇总
     *
     * @param summar
     * @param args
     */
    public static void replenishSummar(JSONObject summar, ChargeArgs args) throws Exception {
        // 此处可以用工厂 生成该对象，后续如果增加多种GPS判断的话
        GpsMatchFactory.getGpsMatch(GpsMatchFactory.deep2).match(summar, args);
        // 补充 adCode信息
        ChargeFieldSupport.summmarAoi(summar, summar.getStr(BaseFields.LATITUDE), summar.getStr(BaseFields.LONGITUDE));

        if (!summar.containsKey("model_code") || BaseFields.defaultVal.equals(summar.getStr("model_code"))) {
            Map<String, String> map = ModeCodeUtil.batteryData(summar.getStr(BaseFields.vin));
            summar.set("model_code", map.get("modelCode"));
        }

    }


    /**
     * 补充开始 汇总数据 [也可以是波段汇总数据]
     *
     * @param summar
     * @param sourceData
     * @return
     */
    public static JSONObject replenishStart(ChargeConstant constant, JSONObject summar, JSONObject sourceData) {
        summar.set(BaseFields.tid, sourceData.getLong(BaseFields.tid));
        summar.set(BaseFields.PARTITION_KEY, sourceData.getStr(BaseFields.PARTITION_KEY));
        summar.set("startChargeTime", sourceData.getLong(BaseFields.tid));
        summar.set("BMS_SOC", sourceData.get(constant.getBmsSoc()));
        summar.set("BMS_SOE", sourceData.get(constant.getBmsSoe()));
        summar.set("BMS_SOH", sourceData.get(constant.getBmsSoh()));
        summar.set("BMS_RMC_ModuleTempMax", sourceData.get(constant.getBmsRmcModuleTempMax()));
        summar.set("BMS_RMC_ModuleTempMin", sourceData.get(constant.getBmsRmcModuleTempMin()));
        summar.set("BMS_ModuleTempaverage", sourceData.get(constant.getBmsModuleTempAverage()));
        summar.set("BMS_BattCurr_RM", sourceData.get(constant.getBmsBattCurr()));
        summar.set("BMS_BattVolt_RM", sourceData.get(constant.getBmsBattVolt()));
        summar.set("ACAmbTemp", sourceData.get(constant.getAcAmbTemp()));
        summar.set("BMS_InnerSOC", sourceData.get(constant.getBmsInnerSOC()));
        summar.set("Tbox_BattSOCLim", sourceData.get(constant.getTboxBattSoc()));
        summar.set("effectiveChargeTime", 0);
        if (sourceData.getInt(constant.getBmsDcchrgConnect()) == 1) {
            // 快充
            // fixme: 无 OBC_ChrgrOutputVolt ，OBC_ChrgrOutputCurr 相关字段
        } else {
            summar.set("OBC_ChrgrOutputVolt", sourceData.get(constant.getObcChrgrOutputVolt()));
            summar.set("OBC_ChrgrOutputCurr", sourceData.get(constant.getObcChrgrOutputCurr()));
        }
        return summar;
    }

    /**
     * 将结束字段数值置空
     *
     * @param bandSummar
     * @return
     */
    public static JSONObject removeEnd(JSONObject bandSummar) {
        bandSummar.remove("endChargeTime");
        bandSummar.remove("end_BMS_SOC");
        bandSummar.remove("end_BMS_SOE");
        bandSummar.remove("end_BMS_SOH");
        bandSummar.remove("end_BMS_RMC_ModuleTempMax");
        bandSummar.remove("end_BMS_RMC_ModuleTempMin");
        bandSummar.remove("end_BMS_ModuleTempaverage");
        bandSummar.remove("end_OBC_ChrgrOutputVolt");
        bandSummar.remove("end_OBC_ChrgrOutputCurr");
        bandSummar.remove("end_BMS_BattCurr_RM");
        bandSummar.remove("end_BMS_BattVolt_RM");
        bandSummar.remove("end_ACAmbTemp");
        bandSummar.remove("end_BMS_InnerSOC");
        bandSummar.remove(ChargeStateModel.END_FLAG);
        return bandSummar;
    }


    /**
     * 补充汇总二级表的 经纬度等相关字段，为了避免重复查询和调用，直接赋值
     *
     * @param summar
     * @param bandSummar
     */
    public static void replenishBandSummar(JSONObject summar, JSONObject bandSummar) {
        bandSummar.set(BaseFields.LATITUDE, summar.get(BaseFields.LATITUDE));
        bandSummar.set(BaseFields.LONGITUDE, summar.get(BaseFields.LONGITUDE));
        bandSummar.set("model_code", summar.get("model_code"));
        bandSummar.set("chargeType", summar.get("chargeType"));
        bandSummar.set("chargeModel", summar.get("chargeModel"));
        bandSummar.set("aoiId", summar.get("aoiId"));
        bandSummar.set("adCode", summar.get("adCode"));
        bandSummar.set("aoiType", summar.get("aoiType"));
        bandSummar.set("poiId", summar.get("poiId"));
        bandSummar.set("poiType", summar.get("poiType"));
        bandSummar.set("custom_type", summar.get("custom_type"));
        bandSummar.set("complete", summar.get("complete"));
    }


    /**
     * 通用状态结束
     *
     * @param args
     * @return
     * @throws Exception
     */
    public static void commonEnd(ChargeArgs args) {
        try {
            JSONObject summar = args.getSummarState().value();
            JSONObject bandSummar = args.getBandSummarState().value();
            // 补充完整 状态结束 --> 由于修改为每条can数据都进行匹配,此处不需要了
//            replenishSummar(summar, args);
            replenishBandSummar(summar, bandSummar);
            // 补充 当前状态的结束信息
            bandSummar.set(ChargeStateModel.END_FLAG, BaseFields.defaultVal);
            replenishEnd(args.getConstant(), bandSummar, args.getPrevEndData());
            bandSummar.set("effectiveChargeTime", 0);
            args.getSummarState().update(summar);
            args.getBandSummarState().update(bandSummar);
        } catch (Exception e) {
            log.error("charge commonEnd happen error:{}", e.getMessage());
            e.printStackTrace();
        }

    }


    /**
     * 补充结束 汇总数据 [也可以是波段汇总数据]
     *
     * @param summar
     * @param sourceData
     * @return
     */
    public static void replenishEnd(ChargeConstant constant, JSONObject summar, JSONObject sourceData) {
        if (!summar.containsKey("chargeSuccOrFail")) {
            summar.set("chargeSuccOrFail", 1);
        }
        summar.set("endChargeTime", sourceData.getLong(BaseFields.tid));
        summar.set("end_BMS_SOC", sourceData.get(constant.getBmsSoc()));
        summar.set("end_BMS_SOE", sourceData.get(constant.getBmsSoe()));
        summar.set("end_BMS_SOH", sourceData.get(constant.getBmsSoh()));
        summar.set("end_BMS_InnerSOC", sourceData.get(constant.getBmsInnerSOC()));
        summar.set("end_BMS_RMC_ModuleTempMax", sourceData.get(constant.getBmsRmcModuleTempMax()));
        summar.set("end_BMS_RMC_ModuleTempMin", sourceData.get(constant.getBmsRmcModuleTempMin()));
        summar.set("end_BMS_ModuleTempaverage", sourceData.get(constant.getBmsModuleTempAverage()));
        if (sourceData.getInt(constant.getBmsDcchrgConnect()) == 1) {
            // fixme 无相关字段  快充
        } else {
            summar.set("end_OBC_ChrgrOutputVolt", sourceData.get(constant.getObcChrgrOutputVolt()));
            summar.set("end_OBC_ChrgrOutputCurr", sourceData.get(constant.getObcChrgrOutputCurr()));
        }
        summar.set("end_BMS_BattCurr_RM", sourceData.get(constant.getBmsBattCurr()));
        summar.set("end_BMS_BattVolt_RM", sourceData.get(constant.getBmsBattVolt()));
        summar.set("end_ACAmbTemp", sourceData.get(constant.getAcAmbTemp()));
    }


    /**
     * 创建明细数据
     *
     * @param args
     * @return
     */
    public static JSONObject createDetail(ChargeArgs args, JSONObject nowData) throws Exception {
        Long startTime = args.getConnectTimeState().value();
        ChargeConstant constant = args.getConstant();
        JSONObject summar = args.getSummarState().value();
        Long chargeStartTime = args.getBandSummarState().value().getLong(args.getConstant().getStartChargeTime());

        JSONObject detail = JSONUtil.createObj();
        detail.set("type", ChargeConstant.detail);
        detail.set("startTid", startTime);
        detail.set("brand", nowData.getStr(constant.getBrand()));
        detail.set("source", nowData.getStr(constant.getSource()));
        detail.set("BMS_ChrgSts", nowData.get(constant.getBmsChrgSts()));
        detail.set("BMS_BattCurr_RM", nowData.get(constant.getBmsBattCurr()));
        detail.set("BMS_RMC_ModuleTempMax", nowData.get(constant.getBmsRmcModuleTempMax()));
        detail.set("BMS_RMC_ModuleTempMin", nowData.get(constant.getBmsRmcModuleTempMin()));
        detail.set("BMS_DCChrgConnect", summar.getStr("BMS_DCChrgConnect"));
        detail.set("OBC_ConnectSts_EV", summar.getStr("OBC_ConnectSts_EV"));
        detail.set("BMS_SOC", nowData.get(constant.getBmsSoc()));
        detail.set("SOH_COR", nowData.get(constant.getSohCor()));
        detail.set("cell_battery_type", nowData.get(constant.getCellBatteryType()));
        detail.set("batter_capcity", nowData.get(constant.getBatterCapcity()));
        detail.set("pack_capacity", nowData.get(constant.getPackCapacity()));
        detail.set("BMS_HeatReq", nowData.get(constant.getBmsHeatReq()));
        detail.set("BMS_CoolReq", nowData.get(constant.getBmsCoolReq()));
        detail.set("BMS_InnerSOC", nowData.get(constant.getBmsInnerSOC()));
        detail.set("BMS_InnerSOCmax", nowData.get(constant.getBmsInnerSocMax()));
        detail.set("BMS_InnerSOCmin", nowData.get(constant.getBmsInnerSocMin()));
        detail.set("BMS_CellVoltMax", nowData.get(constant.getBmsCellVoltMax()));
        detail.set("BMS_CellVoltMin", nowData.get(constant.getBmsCellVoltMin()));
        detail.set("deviceId", nowData.get(BaseFields.vin));
        detail.set("item_time", nowData.get(BaseFields.tid));
        detail.set("vehicletype", nowData.get(VehicleType.VEHICLE_TYPE));
        detail.set("datedt", DateUtil.format(DateUtil.date(nowData.getLong(BaseFields.tid)), DatePattern.NORM_DATE_PATTERN));
        detail.set("model_code", nowData.get(constant.getModelCode()));
        detail.set("BMS_ChrgTime", nowData.get(constant.getBmsChrgTime()));
        detail.set("BMS_SOH", nowData.get(constant.getBmsSoh()));
        detail.set("startChargeTime", chargeStartTime);
        // 新增字段
        detail.set("ACOpenSts", nowData.get(constant.getAcOpenSts()));
        detail.set("ACAmbTemp", nowData.get(constant.getAcAmbTemp()));
        detail.set("BMS_SOE", nowData.get(constant.getBmsSoe()));
        detail.set("aoiId", summar.getStr("aoiId"));
        detail.set("adCode", summar.getStr("adCode"));
        detail.set("aoiType", summar.getStr("aoiType"));
        detail.set("poiId", summar.getStr("poiId"));
        detail.set("poiType", summar.getStr("poiType"));
        detail.set("custom_type", summar.getStr("custom_type"));
        detail.set("chargeType", summar.getStr("chargeType"));
        detail.set("Tbox_BattSOCLim", nowData.getStr(constant.getTboxBattSoc()));
        detail.set("BMS_BattVolt_RM", nowData.getStr(constant.getBmsBattVolt()));
        detail.set(BaseFields.LATITUDE, summar.getStr(BaseFields.LATITUDE));
        detail.set(BaseFields.LONGITUDE, summar.getStr(BaseFields.LONGITUDE));

        return detail;
    }

    /**
     * 优惠电量信息
     *
     * @param nowData
     * @param constant
     * @param chargeFavourable
     * @return
     * @throws Exception
     */
    public static JSONObject createFavourable(JSONObject nowData, ChargeConstant constant, ChargeFavourable chargeFavourable) throws Exception {
        JSONObject favourable = JSONUtil.createObj();
        favourable.set("type", ChargeConstant.favourable);
        favourable.set("deviceId", nowData.get(BaseFields.vin));
        favourable.set("item_time", nowData.get(BaseFields.tid));
        favourable.set("request_time", nowData.get(constant.getRequestTime()));
        favourable.set("vehicletype", nowData.get(VehicleType.VEHICLE_TYPE));
        favourable.set("datedt", DateUtil.format(DateUtil.date(nowData.getLong(BaseFields.tid)), DatePattern.NORM_DATE_PATTERN));
        favourable.set("model_code", nowData.get(constant.getModelCode()));
        favourable.set("custom_type", nowData.get(constant.getCustomType()));
        favourable.set("discountPower", String.format("%.1f", chargeFavourable.getDiscountPower() * 0.1));
        favourable.set("expensivePower", String.format("%.1f", chargeFavourable.getExpensivePower() * 0.1));
        favourable.set("discountTime", chargeFavourable.getDiscountTime());
        favourable.set("expensiveTime", chargeFavourable.getExpensiveTime());

        return favourable;
    }


}
